package com.sheepone.util.structure;

/**
 * @author Miss.杨
 * @description 索引工具类
 * @since 2024/3/17 - 23:18
 */
public class IndexUtil {
    /**
     * 若arrays.length==n，前n-1个数组应该是区间，
     * 最后一个数据array.length==n-1,该数组每个值对标每个区间
     * 默认采用(]比较
     * 不符合区间则为-1
     *
     * @param arrays
     * @return
     */
    public static int getIntervalIndexForInterval(double[]... arrays) {
        int size = arrays.length - 1;
        double[] values = arrays[size];
        if (size != values.length) {
            throw new IllegalArgumentException("数组长度不一致");
        }
        int[] indexes = new int[size];
        for (int i = 0, index; i < size; i++) {
            index = -1;
            for (int j = 0; j < arrays[i].length - 1; j++) {
                // 查询每个值在对应区间的索引
                if (values[i] > arrays[i][j] && values[i] <= arrays[i][j + 1]) {
                    index = j;
                    break;
                }
            }
            if (index == -1) {
                return -1;
            }
            indexes[i] = index;
        }
        if (size == 1) {
            return indexes[0];
        }
        int[] accumulate = new int[size - 1];
        // 数组长度累乘，不包括最后一阶层
        accumulate[0] = arrays[0].length - 1;
        for (int i = 1; i < size - 1; i++) {
            accumulate[i] = accumulate[i - 1] * (arrays[i].length - 1);
        }
        int index = 0;
        for (int i = size - 1; i > 0; i--) {
            index += indexes[i] * accumulate[i - 1];
        }
        return index + indexes[0];
    }

    public static int getIntervalIndexForIndicator(double[] maxs, double[] mins, double[] steps, double[] values) {
        int size = values.length;
        if (size != mins.length || size != steps.length || size != maxs.length) {
            throw new IllegalArgumentException("数组长度不一致");
        }
        int[] indexes = new int[size];
        for (int i = 0; i < size; i++) {
            if (values[i] <= mins[i] || values[i] > maxs[i]) {
                return -1;
            }
            double v = values[i] - mins[i];
            indexes[i] = (int) (v % steps[i] == 0 ? (v / steps[i] - 1) : (v / steps[i]));
        }
        if (size == 1) {
            return indexes[0];
        }
        int[] accumulate = new int[size - 1];
        // 数组长度累乘，不包括最后一阶层
        accumulate[0] = getIntervalNum(maxs[0], mins[0], steps[0]);
        for (int i = 1; i < size - 1; i++) {
            accumulate[i] = accumulate[i - 1] * getIntervalNum(maxs[i], mins[i], steps[i]);
        }
        int index = 0;
        for (int i = size - 1; i > 0; i--) {
            index += indexes[i] * accumulate[i - 1];
        }
        return index + indexes[0];
    }


    /**
     * 获取区间个数
     *
     * @param max  区间最大值
     * @param min  区间最小值
     * @param step 区间步长
     * @return 区间个数
     */
    public static int getIntervalNum(double max, double min, double step) {
        return (int) ((max - min) / step);
    }



}
